home *** CD-ROM | disk | FTP | other *** search
- /*
- pro_frame.c
- $Revision: 1.15 $ $Date: 1993/10/06 00:01:25 $
- $Source: /cmplrs.src/v4.00/libdwarf/RCS/pro_frame.c,v $
-
- Frame information routines
- */
-
- #include <stdio.h>
- #include <string.h>
- #include <limits.h>
- #include "pro_incl.h"
- #include "pro_frame.h"
-
- static void _dwarf_pro_add_to_fde(Dwarf_P_Fde fde, Dwarf_P_Frame_Pgm inst);
-
- /*-------------------------------------------------------------------------
- This functions adds a cie struct to the debug pointer. Its in the
- form of a linked list.
- augmenter: string reps augmentation (implementation defined)
- code_align: alignment of code
- data_align: alignment of data
- init_bytes: byts having initial instructions
- init_n_bytes: number of bytes of initial instructions
- --------------------------------------------------------------------------*/
- Dwarf_Unsigned
- dwarf_add_frame_cie(
- Dwarf_P_Debug dbg,
- char *augmenter,
- Dwarf_Small code_align,
- Dwarf_Small data_align,
- Dwarf_Small return_reg,
- Dwarf_Ptr init_bytes,
- Dwarf_Unsigned init_n_bytes,
- Dwarf_Error *error)
- {
- Dwarf_P_Cie curcie;
-
- if (dbg->de_frame_cies == NULL) {
- dbg->de_frame_cies = (Dwarf_P_Cie)
- _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Cie_s));
- if (dbg->de_frame_cies == NULL) {
- DWARF_P_DBG_ERROR(dbg,DW_DLE_CIE_ALLOC,DW_DLV_NOCOUNT);
- }
- curcie = dbg->de_frame_cies;
- dbg->de_n_cie = 1;
- dbg->de_last_cie = curcie;
- }
- else {
- curcie = dbg->de_last_cie;
- curcie->cie_next = (Dwarf_P_Cie)
- _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Cie_s));
- if (curcie->cie_next == NULL) {
- DWARF_P_DBG_ERROR(dbg,DW_DLE_CIE_ALLOC,DW_DLV_NOCOUNT);
- }
- curcie = curcie->cie_next;
- dbg->de_n_cie++;
- dbg->de_last_cie = curcie;
- }
- curcie->cie_version = DW_CIE_VERSION;
- curcie->cie_aug = augmenter;
- curcie->cie_code_align = code_align;
- curcie->cie_data_align = data_align;
- curcie->cie_ret_reg = return_reg;
- curcie->cie_inst = (char *) init_bytes;
- curcie->cie_inst_bytes = init_n_bytes;
- curcie->cie_next = NULL;
- return dbg->de_n_cie;
- }
-
-
- /*-------------------------------------------------------------------------
- This functions adds a fde struct to the debug pointer. Its in the
- form of a linked list.
- die: subprogram/function die corresponding to this fde
- cie: cie referred to by this fde, obtained from call to
- add_frame_cie() routine.
- virt_addr: beginning address
- code_len: length of code reps by the fde
- --------------------------------------------------------------------------*/
- Dwarf_Unsigned
- dwarf_add_frame_fde(
- Dwarf_P_Debug dbg,
- Dwarf_P_Fde fde,
- Dwarf_P_Die die,
- Dwarf_Unsigned cie,
- Dwarf_Unsigned virt_addr,
- Dwarf_Unsigned code_len,
- Dwarf_Unsigned symidx,
- Dwarf_Error *error)
- {
- Dwarf_P_Fde curfde;
-
- fde->fde_die = die;
- fde->fde_cie = cie;
- fde->fde_initloc = virt_addr;
- fde->fde_r_symidx = symidx;
- fde->fde_addr_range = code_len;
-
- curfde = dbg->de_last_fde;
- if (curfde == NULL) {
- dbg->de_frame_fdes = fde;
- dbg->de_last_fde = fde;
- dbg->de_n_fde = 1;
- }
- else {
- curfde->fde_next = fde;
- dbg->de_last_fde = fde;
- dbg->de_n_fde++;
- }
- return dbg->de_n_fde;
- }
-
- /*-------------------------------------------------------------------
- Create a new fde
- ---------------------------------------------------------------------*/
- Dwarf_P_Fde
- dwarf_new_fde (Dwarf_P_Debug dbg, Dwarf_Error *error)
- {
- Dwarf_P_Fde fde;
-
- fde = (Dwarf_P_Fde)
- _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Fde_s));
- if (fde == NULL) {
- DWARF_P_DBG_ERROR(dbg,DW_DLE_FDE_ALLOC,(Dwarf_P_Fde) DW_DLV_BADADDR);
- }
- fde->fde_next = NULL;
- fde->fde_inst = NULL;
- fde->fde_n_inst = 0;
- fde->fde_n_bytes = 0;
- fde->fde_last_inst = NULL;
- return fde;
- }
-
- /*------------------------------------------------------------------------
- Add cfe_offset instruction to fde
- -------------------------------------------------------------------------*/
- Dwarf_P_Fde
- dwarf_fde_cfa_offset(
- Dwarf_P_Fde fde,
- Dwarf_Unsigned reg,
- Dwarf_Signed offset,
- Dwarf_Error *error)
- {
- Dwarf_Ubyte opc, regno;
- char *ptr;
- Dwarf_P_Frame_Pgm curinst;
- int nbytes;
-
- curinst = (Dwarf_P_Frame_Pgm)
- _dwarf_p_get_alloc(NULL,sizeof(struct Dwarf_P_Frame_Pgm_s));
- if (curinst == NULL) {
- DWARF_P_DBG_ERROR(NULL,DW_DLE_FPGM_ALLOC,(Dwarf_P_Fde) DW_DLV_BADADDR);
- }
- opc = DW_CFA_offset;
- regno = reg;
- if (regno & 0xc0) {
- DWARF_P_DBG_ERROR(NULL,DW_DLE_REGNO_OVFL,(Dwarf_P_Fde) DW_DLV_BADADDR);
- }
- opc = opc | regno; /* lower 6 bits are register number */
- curinst->dfp_opcode = opc;
- ptr = _dwarf_pro_encode_leb128(offset, &nbytes);
- curinst->dfp_args = ptr;
- curinst->dfp_nbytes = nbytes;
- curinst->dfp_next = NULL;
-
- _dwarf_pro_add_to_fde(fde,curinst);
- return fde;
- }
-
- /*
- Generic routine to add opcode to fde instructions. val1 and
- val2 are parameters whose interpretation depends on the 'op'.
- */
- Dwarf_P_Fde
- dwarf_add_fde_inst(
- Dwarf_P_Fde fde,
- Dwarf_Small op,
- Dwarf_Unsigned val1,
- Dwarf_Unsigned val2,
- Dwarf_Error *error
- )
- {
- Dwarf_P_Frame_Pgm curinst;
- int nbytes, nbytes1, nbytes2;
- Dwarf_Ubyte db;
- Dwarf_Half dh;
- Dwarf_Word dw;
- Dwarf_Unsigned du;
- char *ptr, *ptr1, *ptr2;
-
- /* debug trace. uncomment if needed.
- printf ("add_fde: op = %d, val1 = 0x%llx, val2 = 0x%llx \n",
- op, val1, val2);
- */
-
- nbytes = 0;
- ptr = NULL;
- curinst = (Dwarf_P_Frame_Pgm)
- _dwarf_p_get_alloc(NULL,sizeof(struct Dwarf_P_Frame_Pgm_s));
- if (curinst == NULL) {
- _dwarf_p_error(NULL, error, DW_DLE_FPGM_ALLOC);
- return((Dwarf_P_Fde)DW_DLV_BADADDR);
- }
-
- switch (op) {
-
- case DW_CFA_advance_loc:
- if (val1 <= 0x3f) {
- db = val1;
- op |= db;
- }
- else if (val1 <= UCHAR_MAX) {
- op = DW_CFA_advance_loc1;
- db = val1;
- ptr = (char *) _dwarf_p_get_alloc(NULL, 1);
- if (ptr == NULL) {
- _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
- return((Dwarf_P_Fde)DW_DLV_BADADDR);
- }
- memcpy((void *)ptr, (const void *)&db,1);
- nbytes = 1;
- }
- else if (val1 <= USHRT_MAX) {
- op = DW_CFA_advance_loc2;
- dh = val1;
- ptr = (char *) _dwarf_p_get_alloc(NULL, 2);
- if (ptr == NULL) {
- _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
- return((Dwarf_P_Fde)DW_DLV_BADADDR);
- }
- memcpy((void *)ptr, (const void *)&dh,2);
- nbytes = 2;
- }
- else if (val1 <= ULONG_MAX) {
- op = DW_CFA_advance_loc4;
- dw = val1;
- ptr = (char *) _dwarf_p_get_alloc(NULL, 4);
- if (ptr == NULL) {
- _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
- return((Dwarf_P_Fde)DW_DLV_BADADDR);
- }
- memcpy((void *)ptr, (const void *)&dw,4);
- nbytes = 4;
- }
- else {
- op = DW_CFA_MIPS_advance_loc8;
- du = val1;
- ptr = (char *)_dwarf_p_get_alloc(NULL, sizeof(Dwarf_Unsigned));
- if (ptr == NULL) {
- _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
- return((Dwarf_P_Fde)DW_DLV_BADADDR);
- }
- memcpy((void *)ptr, (const void *)&du,8);
- nbytes = 8;
- }
- break;
-
- case DW_CFA_offset:
- if (val1 <= MAX_6_BIT_VALUE) {
- db = val1;
- op |= db;
- ptr = _dwarf_pro_encode_leb128(val2, &nbytes);
- }
- else {
- op = DW_CFA_offset_extended;
-
- ptr1 = _dwarf_pro_encode_leb128(val1, &nbytes1);
- ptr2 = _dwarf_pro_encode_leb128(val2, &nbytes2);
- ptr = (char *) _dwarf_p_get_alloc(NULL, nbytes1+nbytes2);
- memcpy(ptr, ptr1, nbytes1);
- memcpy(ptr+nbytes1, ptr2, nbytes2);
- _dwarf_p_dealloc(NULL, ptr1);
- _dwarf_p_dealloc(NULL, ptr2);
- nbytes = nbytes1 + nbytes2;
- }
- break;
-
- case DW_CFA_undefined:
- case DW_CFA_same_value:
- ptr = _dwarf_pro_encode_leb128(val1, &nbytes);
- break;
-
- case DW_CFA_register:
- case DW_CFA_def_cfa:
- ptr1 = _dwarf_pro_encode_leb128(val1, &nbytes1);
- ptr2 = _dwarf_pro_encode_leb128(val2, &nbytes2);
- ptr = (char *) _dwarf_p_get_alloc(NULL, nbytes1+nbytes2);
- memcpy(ptr, ptr1, nbytes1);
- memcpy(ptr+nbytes1, ptr2, nbytes2);
- _dwarf_p_dealloc(NULL, ptr1);
- _dwarf_p_dealloc(NULL, ptr2);
- nbytes = nbytes1 + nbytes2;
- break;
-
- case DW_CFA_def_cfa_register:
- case DW_CFA_def_cfa_offset:
- ptr = _dwarf_pro_encode_leb128(val1, &nbytes);
- break;
-
- default:
- break;
- }
-
- curinst->dfp_opcode = op;
- curinst->dfp_args = ptr;
- curinst->dfp_nbytes = nbytes;
- curinst->dfp_next = NULL;
-
- _dwarf_pro_add_to_fde(fde, curinst);
- return fde;
- }
-
-
- /*------------------------------------------------------------------------
- instructions are added to fde in the form of a linked
- list. This functions manages the linked list
- -------------------------------------------------------------------------*/
- void
- _dwarf_pro_add_to_fde(Dwarf_P_Fde fde, Dwarf_P_Frame_Pgm curinst)
- {
- if (fde->fde_last_inst) {
- fde->fde_last_inst->dfp_next = curinst;
- fde->fde_last_inst = curinst;
- fde->fde_n_inst++;
- fde->fde_n_bytes += curinst->dfp_nbytes + sizeof(Dwarf_Ubyte) ;
- }
- else {
- fde->fde_last_inst = fde->fde_inst = curinst;
- fde->fde_n_inst = 1;
- fde->fde_n_bytes = curinst->dfp_nbytes + sizeof(Dwarf_Ubyte);
- }
- }
-